package web

import (
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"net/http"
	"regexp"
	"time"
	"webook/internal/domain"
	"webook/internal/service"
)

// UserHandler 用户相关的路由
type UserHandler struct {
	svc         *service.UserService
	emailExp    *regexp.Regexp
	passwordExp *regexp.Regexp
}

func NewUserHandler(svc *service.UserService) *UserHandler {
	var (
		emailRegexPattern    = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"
		passwordRegexPattern = "^[a-zA-Z\\d]{8,}$"
	)
	emailExp := regexp.MustCompile(emailRegexPattern)
	passwordRegex := regexp.MustCompile(passwordRegexPattern)
	return &UserHandler{
		emailExp:    emailExp,
		passwordExp: passwordRegex,
		svc:         svc,
	}
}

func (u *UserHandler) RegisterRoutes(server *gin.Engine) {
	ug := server.Group("/users")
	ug.POST("/signup", u.SignUp)
	ug.POST("/login", u.Login)
	ug.POST("/loginJwt", u.LoginJwt)
	ug.POST("/profile", u.Profile)
	ug.POST("/edit", u.Edit)

}

// 编辑用户信息
func (u *UserHandler) Edit(c *gin.Context) {
	var editUserRequest struct {
		Id       int64  `json:"id" binding:"required"`
		NickName string `json:"nickname" binding:"min=1,max=64"`
		Birthday string `json:"birthday"`
		Profile  string `json:"profile" binding:"min=6,max=1023"`
		Email    string `json:"email"`
	}
	if err := c.ShouldBindJSON(&editUserRequest); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg": err.Error(),
		})
	}

	err := u.svc.Edit(c, domain.User{
		Id:       editUserRequest.Id,
		Nickname: editUserRequest.NickName,
		Birthday: editUserRequest.Birthday,
		Profile:  editUserRequest.Profile,
		Email:    editUserRequest.Email,
	})
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"msg": "更新用户信息失败",
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": "更新用户信息成功",
	})

}

// 获取用户信息
func (u *UserHandler) Profile(c *gin.Context) {

	user, _ := c.Get(UserClaimsKey)
	claims, ok := user.(*UserClaims)
	if !ok {
		c.String(http.StatusOK, "查询用户信息失败")
		return
	}
	fmt.Println(claims)
	//var userId int64 = c.GetInt64("userId")
	// 转为int64
	userInfo, err := u.svc.GetUserProfile(c, claims.UserId)
	if err != nil {
		c.String(http.StatusOK, "查询用户信息失败")
		return
	}
	c.JSON(http.StatusOK, userInfo)
	return
}

// 用户注册
func (u *UserHandler) SignUp(c *gin.Context) {
	type SignUpReq struct {
		Email           string `json:"email"`
		ConfirmPassword string `json:"confirm_password"`
		Password        string `json:"password"`
	}

	var req SignUpReq
	if err := c.Bind(&req); err != nil {
		c.String(http.StatusBadRequest, "请求参数错误")
		return
	}

	// 检查邮箱格式
	if !u.emailExp.MatchString(req.Email) {
		c.String(http.StatusOK, "邮箱格式不正确")
		return
	}

	// 检查密码格式
	if !u.passwordExp.MatchString(req.Password) {
		c.String(http.StatusOK, "密码格式不正确")
		return
	}

	if req.Password != req.ConfirmPassword {
		c.String(http.StatusOK, "密码不一致")
		return
	}
	err := u.svc.SignUp(c, domain.User{
		Email:    req.Email,
		Password: req.Password,
	})
	if err != nil {
		c.String(http.StatusOK, err.Error())
		return
	}
	c.String(http.StatusOK, "注册成功")
}

func (u *UserHandler) Login(c *gin.Context) {
	type LoginReq struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}
	var req LoginReq
	if err := c.Bind(&req); err != nil {
		c.String(http.StatusBadRequest, "请求参数错误")
		return
	}
	user, err := u.svc.Login(c, domain.User{
		Email:    req.Email,
		Password: req.Password,
	})

	if err == service.ErrUserNotFound {
		c.String(http.StatusBadRequest, "用户不存在")
		return
	}
	if err != nil {
		c.String(http.StatusOK, "登录失败")
		return
	}

	sess := sessions.Default(c)
	sess.Set("userId", user.Id)
	sess.Options(sessions.Options{
		MaxAge: 30 * 60,
	})
	sess.Save()
	c.String(http.StatusOK, "登录成功")
}
func (u *UserHandler) LoginJwt(c *gin.Context) {
	type LoginReq struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}
	var req LoginReq
	if err := c.Bind(&req); err != nil {
		c.String(http.StatusBadRequest, "请求参数错误")
		return
	}
	user, err := u.svc.Login(c, domain.User{
		Email:    req.Email,
		Password: req.Password,
	})

	if err == service.ErrUserNotFound {
		c.String(http.StatusBadRequest, "用户不存在")
		return
	}
	if err != nil {
		c.String(http.StatusOK, "登录失败")
		return
	}
	claims := UserClaims{
		UserId:    user.Id,
		UserAgent: c.GetHeader("User-Agent"),
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 60 * 60 * 24)),
		},
	}
	// 生成一个token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenStr, err := token.SignedString([]byte("dlfkhjkdlhjkdgh"))
	if err != nil {
		c.String(http.StatusOK, "登录失败")
		return
	}
	c.Header("x-jwt-token", tokenStr)

	c.String(http.StatusOK, "登录成功")
}

type UserClaims struct {
	jwt.RegisteredClaims
	UserId    int64
	UserAgent string
}

const UserClaimsKey string = "user_claims"
